/*
 * @Description: unit 1
 * @version: 0.0.1
 * @Author: 小妖怪
 * @Date: 2021-07-24 22:48:10
 * @LastEditors: Mr.小妖怪
 * @LastEditTime: 2021-07-25 11:10:25
 * @FilePath: \study_typescript\demo\index.ts
 */
// 类型为小写
// 类型 声明变量，并同时指定其类型为number
let a: number;
a = 10
console.log(a);
// 运行错误 变量 a 的类型为 number 不能赋值为 string
// a = 'hello'
console.log(a);

// 声明变量并同时赋值
let c: boolean = true;
console.log(c);

// 变量在声明和赋值同时进行时， TS 自动对变量进行类型检测
let d = false
console.log(c);

// 在 JS 中函数不会考虑参数的类型及个数
// 返回值类型为 number 类型
function sum(a, b: number): number {
  return a + b
}
// ret 的类型为 number
let ret = sum(22, 31)
console.log(sum(12, 23));

// type
{
  // 字面量
  let a: 10 // 限定为
  // a = 11  错误 a 的值为 10
  let b: 'male' | 'female' // "|" 或者 （联合类型）
  b = 'male'
  // any 任意类型，关闭 TS 类型检查 不建议使用
  let d: any
  // 声明变量不指定类型，TS 自动判断变量类型为 any （隐式转换）
  let c;

  // unknown 表示未知类型 类型安全的 any 不能直接赋值给其他变量
  let e: unknown
  e = 1;
  e = 'hello'

  let s: string;
  // d 是 any 类型，可以赋值给任意变量
  s = d
  e = d
  // 错误，不能将 unknown 类型赋值给 string 类型
  // s = e
  if (typeof e === 'string') {
    s = e
  }
  // 类型断言，告诉 TS 实际类型值
  s = e as string // <string>e
  s = <string>e
}
// 返回值
{
  // void 用来表示空，表示没有返回值或 undefined / null
  function fn(num: number): void {
    if (num > 0) { }
    // 有返回时 将会报错
    // return true
    return undefined
  }
  function fn1(num): string | number | void | never {
    if (num > 0) {
      return 1
    } else if (num === 'ss') {
      return 'hello'
    }
  }
  // 表示什么没有值
  function fn2(): never {
    throw new Error('22')
  }
  console.log(fn1(''));
}

{
  // object 表示一个对象
  let a: object
  a = {};
  a = function () { }

  // {} 用来指定对象中可以包含哪些属性
  // 属性后面加上 ? 表示该属性可选
  let b: { name: string }
  b = { name: 'justin' }

  // [propName:string]:any 表示任意类型的属性
  let c: { name: string, [s: string]: any }
  c = { name: 'justin', age: 12, gender: 'male' }

  /**
   * 设置函数结构的类型声明
   */
  let d: (a: number, b: number) => number
  d = function (n1, n2): number {
    return n1 + n2
  }
  // string[] 表示字符串数组
  let e: string[]
  // number[] 表示数值数组
  let f: number[]
  let g: Array<string>
  g = ['1', '2']
}

{
  /**
   * 元组，固定长度的数组
   */
  let h: [string, string]
  h = ['hello', 'world']

  console.log(h);

  /**
   *  enum 枚举
   */

  enum Gender {
    Male = 0,
    Female = 1
  }
  let i: { name: string, gender: Gender }
  i = {
    name: 'justin',
    gender: Gender.Female
  }

  console.log(i.gender === Gender.Female)

  // & 表示同时 | 表或者
  let j: string | number
  let g: { name: string } & { age: number }
  g = { name: 'lucy', age: 22 }

  // 类型的别名
  type tt = 1 | 2 | 3 | 4
  let f: tt
  f = 1
}